/*
 * TODO language 
 * Copyright (c) 2010 TODO Team
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef TODO_API_H
#define TODO_API_H
#include <cstdarg>
#include <string>

namespace todo {
	
class Type;
Type** TypeList(unsigned int num, ...);

void vtsprintf(std::string&, const char*, va_list);
void tsprintf(std::string&, const char*, ...);
void tprintlnf(const char*, ...);
void tprintf(const char*, ...);

}

#define CALL_METHOD(_v, _mname, _prms) \
	(_v)->type->call_method(_mname, _v, _prms)
	
#define CALL_STATIC_METHOD(_v, _mname, _prms) \
	(_v)->type->call_method(_mname, NULL, _prms)

#define DESTROY(_v) \
	(_v)->type->dealloc(_v)
	
#define COPY(_v) \
	(_v)->type->copy(_v)

#define IS_TRUE(_v) \
	((_v->type == TypeManager::booltype && BOOL_V(*_v) == true) \
			|| (_v->type == TypeManager::inttype && INT_V(*_v)) \
			|| (_v->type == TypeManager::doubletype && DOUBLE_V(*_v)))
			
#define IS_FALSE(_v) \
	((_v->type == TypeManager::booltype && BOOL_V(*_v) == false) \
			|| (_v->type == TypeManager::inttype && INT_V(*_v) == 0) \
			|| (_v->type == TypeManager::doubletype && DOUBLE_V(*_v) == 0))

/**
 * Helper to get argument data
 */
#define ARG(x) args->args[(x)]
#define ARGC() args->args.size()

/**
 * Helper to get the specific datatype pointer from Value pointer
 */
#define STR_P(x)    ((std::string*)(x)->data.value)
#define VECTOR_P(x) ((todo_vector*)(x)->data.value)
#define MAP_P(x)    ((todo_map*)(x)->data.value)

/**
 * Helper to get the specific datatype value of a Value pointer
 */
#define STR_V(x)    (*STR_P(x))
#define BOOL_V(x)   ((x)->data.boolv)
#define INT_V(x)    ((x)->data.longv)
#define DOUBLE_V(x) ((x)->data.doublev)
#define VECTOR_V(x) (*VECTOR_P(x))
#define MAP_V(x)    (*MAP_P(x))

/**
 * Helper to get a type pointer by name
 */
#define TYPE_P(x) typeman.get_type(x)

/**
 * Helper to alloc a specific Value* by name
 */
#define NEW(x) TYPE_P(x)->alloc()

#define TODO_STATIC_METHOD_ARGS GCValue* __unused_value__, const ArgValues* args
#define TODO_STATIC_METHOD(klass, method) GCValue* klass::method(TODO_STATIC_METHOD_ARGS)

#define TODO_METHOD_ARGS GCValue* value, const ArgValues* args
#define TODO_METHOD(klass, method) GCValue* klass::method(TODO_METHOD_ARGS)

#define TODO_FUNCTION_ARGS TODO_STATIC_METHOD_ARGS
#define TODO_FUNCTION(klass, method) GCValue* klass::method(TODO_FUNCTION_ARGS)

#endif // TODO_API_H
